package com.boc.news.beans.json;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

public class JsonConversion {
	private Map map;
	private ArrayList converArray;
	public JsonConversion(Map map){
		this.map = map;
	}
	
	public JsonConversion(Collection collection){
		this.converArray = (collection == null) ?new ArrayList() :new ArrayList(collection);
	}
	
	public static String valueToString(Object value) throws JsonException {
        if (value == null || value.equals(null)) {
            return "null";
        }
        if (value instanceof Number) {
            return numberToString((Number) value);
        }
        if (value instanceof Boolean) {
            return value.toString();
        }
        if (value instanceof Map) {
            return new JsonConversion((Map)value).toString();
        }
        
        if (value instanceof Collection) {
            return new JsonArray((Collection)value).toString();
        }
        if (value.getClass().isArray()) {
            return new JsonArray(value).toString();
        }
        
        return quote(value.toString());
    }
	
	public static String quote(String string) {
        if (string == null || string.length() == 0) {
            return "\"\"";
        }

        char         b;
        char         c = 0;
        int          i;
        int          len = string.length();
        StringBuffer sb = new StringBuffer(len + 4);
        String       t;

        sb.append('"');
        for (i = 0; i < len; i += 1) {
            b = c;
            c = string.charAt(i);
            switch (c) {
            case '\\':
            case '"':
                sb.append('\\');
                sb.append(c);
                break;
            case '/':
                if (b == '<') {
                    sb.append('\\');
                }
                sb.append(c);
                break;
            case '\b':
                sb.append("\\b");
                break;
            case '\t':
                sb.append("\\t");
                break;
            case '\n':
                sb.append("\\n");
                break;
            case '\f':
                sb.append("\\f");
                break;
            case '\r':
                sb.append("\\r");
                break;
            default:
                if (c < ' ' || (c >= '\u0080' && c < '\u00a0') ||
                               (c >= '\u2000' && c < '\u2100')) {
                    t = "000" + Integer.toHexString(c);
                    sb.append("\\u" + t.substring(t.length() - 4));
                } else {
                    sb.append(c);
                }
            }
        }
        sb.append('"');
        return sb.toString();
    }
	
	public static String numberToString(Number n)
	    throws JsonException {
		if (n == null) {
		    throw new JsonException("Null pointer");
		}
		testValidity(n);
		
		String s = n.toString();
		if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
		    while (s.endsWith("0")) {
		        s = s.substring(0, s.length() - 1);
		    }
		    if (s.endsWith(".")) {
		        s = s.substring(0, s.length() - 1);
		    }
		}
		return s;
	}
	
	public static void testValidity(Object o) throws JsonException {
        if (o != null) {
            if (o instanceof Double) {
                if (((Double)o).isInfinite() || ((Double)o).isNaN()) {
                    throw new JsonException(
                        "JSON does not allow non-finite numbers.");
                }
            } else if (o instanceof Float) {
                if (((Float)o).isInfinite() || ((Float)o).isNaN()) {
                    throw new JsonException(
                        "JSON does not allow non-finite numbers.");
                }
            }
        }
    }
	
	public String toString() {
        try {
            Iterator     keys = keys();
            StringBuffer sb = new StringBuffer("{");

            while (keys.hasNext()) {
                if (sb.length() > 1) {
                    sb.append(',');
                }
                Object o = keys.next();
                sb.append(quote(o.toString()));
                sb.append(':');
                sb.append(valueToString(this.map.get(o)));
            }
            sb.append('}');
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }
	
	public Iterator keys() {
        return this.map.keySet().iterator();
    }
}
